package com.seed.core.builder.search;

import cn.hutool.core.util.StrUtil;
import com.seed.core.column.Column;
import com.seed.core.enumeration.PropertyType;
import com.seed.core.enumeration.SqlOp;
import com.seed.core.pojo.seed.Relation;
import com.seed.core.pojo.seed.Seed;
import com.seed.core.query.pojo.Searched;
import com.seed.util.SeedKit;
import com.seed.util.StrKit;

import java.util.*;

public class SearchedBuilder {

    private final Seed seed; // 当前访问的模块
    private final List<String> values; // 搜索配置，形如：column1_eq=value1,cross.column2_eq=value2,column2_eq
    private Map<String, String> params; // 客户端提交的参数，形如：{column2_eq: value2}

    public SearchedBuilder(Seed seed, List<String> values) {
        this.seed = seed;
        this.values = values;
    }

    public SearchedBuilder(Seed seed, List<String> values, Map<String, String> params) {
        this(seed, values);
        this.params = params;
    }

    public Map<String, Searched> build() {
        Map<String, Searched> ret = new LinkedHashMap<>();
        for(String search: format(values, params)) build(ret, seed, search);

        return ret;
    }

    public static void build(Map<String, Searched> parent, Seed seed, String... searches) {
        if(searches == null) return;

        for (String search: searches) build(parent, seed, search);
    }

    public static void build(Map<String, Searched> parent, Seed seed, String search) {
        String[] declareAndOpAndValues = StrKit.cutInTwo(search, '=', false);
        String declareAndOp = declareAndOpAndValues[0];
        String value = declareAndOpAndValues[1];

        Map<String, Column> columns = seed.getColumns();
        String[] declareAndOps = StrKit.cutInTwo(declareAndOp, '_', true);
        String declare = StrUtil.toUnderlineCase(declareAndOps[0]);
        String op = declareAndOps[1];
        if(declare.contains(".")) {
            String[] items = StrKit.cutInTwo(declare, '.', false);
            String cross = items[0];
            String subDeclareAndOp = items[1] + '_' + op;
            String subSearch = StrUtil.isBlank(value) ? subDeclareAndOp : subDeclareAndOp + '=' + value;
            Relation relation = SeedKit.getRelation(seed, cross);
            Searched searched = parent.get(cross);
            if(searched == null) searched = new Searched(relation);
            build(searched, relation.targetSeed(), subSearch);
            parent.put(cross, searched);
        } else {
            if("".equals(declare)) {
                Searched searched = parent.get(search);
                if(searched == null) parent.put(search, new Searched(PropertyType.none, value));
            } else if("*".equals(declare)) {
                Searched searched = parent.get(search);
                if(searched == null) parent.put(search, new Searched(PropertyType.asterisk, value));
            } else {
                Column column = columns.get(declare);
                if(column == null) {
                    String subDeclareAndOp = "_" + op;
                    String subSearch = StrUtil.isBlank(value) ? subDeclareAndOp : subDeclareAndOp + '=' + value;
                    Relation relation = SeedKit.getRelation(seed, declare);
                    Searched searched = parent.get(declare);
                    if(searched == null) searched = new Searched(relation);
                    build(searched, relation.targetSeed(), subSearch);
                    parent.put(declare, searched);
                } else {
                    String key = String.format("%s_%s=%s", declare, op, value);
                    Searched searched = parent.get(key);
                    if(searched == null) parent.put(key, new Searched(column, value));
                }
            }
        }
    }

    /**
     * 格式化搜索配置项，将提供的参数补充到配置上
     * @return 格式化后的配置
     */
    private static List<String> format(List<String> values, Map<String, String> params){
        List<String> ret = new ArrayList<>();
        for(String search: values) {
            String[] items = search.split("=");
            String pathAndOp = items[0];
            String value = items.length > 1 ? items[1] : null;

            int pos = pathAndOp.lastIndexOf('_');
            String finalColumn = pathAndOp.substring(0, pos);
            SqlOp op = SqlOp.valueOf(pathAndOp.substring(pos + 1));
            if(op.equals(SqlOp.isNull) || op.equals(SqlOp.isNotNull)) {
                ret.add(String.format("%s_%s", finalColumn, op.name()));
            } else if(value == null) {
                value = params.get(pathAndOp);
                if(StrUtil.isNotBlank(value)) ret.add(String.format("%s=%s", pathAndOp, value));
                // 客户端没提供值的忽略掉
            } else {
                ret.add(search);
            }
        }

        return ret;
    }
}
